#include "../ILAppBase.h"
#include "ILControl.h"
#include "ILButton.h"
#include "ILImage.h"
#include "ILLabel.h"

#define IL_TEXT_BUTTON_DISABLE_COLOR 0x999999

static void il_ctrl_text_button_paint(il_control* ctrl_p)
{
    il_button* button_p = (il_button*)ctrl_p;
    il_rect* area_p = NULL;
    ILUINT color;
    ILINT layer;

    if(!button_p || !button_p->elem.label || button_p->status < IL_BUTTON_UP || button_p->status >= IL_BUTTON_TYPE_MAX)
        return;

    area_p = &ctrl_p->area;
    layer = il_get_layer_hdlr_by_buffer(button_p->base.paint_buf);

    if(layer < 0 || il_set_layer_clip_ex(layer, area_p) == IL_IGNORE)
        return;

    button_p->elem.label->get_text_color((il_control*)button_p->elem.label, &color);

    if(button_p->status == IL_BUTTON_UP)
    {
        button_p->elem.label->set_layout((il_control*)button_p->elem.label, button_p->elem.label->layout);
    }
    else if(button_p->status == IL_BUTTON_DISABLE)
    {
        button_p->elem.label->set_text_color((il_control*)button_p->elem.label, IL_TEXT_BUTTON_DISABLE_COLOR);
    }
    else //if(button_p->status == IL_BUTTON_DOWN)
    {
        button_p->elem.label->text_y_off++;
    }

    button_p->elem.label->base.paint_hdlr((il_control*)button_p->elem.label);
    button_p->elem.label->set_text_color((il_control*)button_p->elem.label, color);
    il_reset_layer_clip(layer);
}

static void il_ctrl_image_button_paint(il_control* ctrl_p)
{
    il_button* button_p = (il_button*)ctrl_p;
    il_rect* area_p = NULL;
    ILINT layer;

    if(!ctrl_p)
        return;

    area_p = &ctrl_p->area;
    layer = il_get_layer_hdlr_by_buffer(button_p->base.paint_buf);

    if(layer < 0 || il_set_layer_clip_ex(layer, area_p) == IL_IGNORE)
        return;

    if(button_p->status >= IL_BUTTON_UP && button_p->status < IL_BUTTON_TYPE_MAX)
    {
        if(button_p->elem.images[button_p->status])
        {
            button_p->elem.images[button_p->status]->base.paint_hdlr((il_control*)button_p->elem.images[button_p->status]);
        }
    }

    il_reset_layer_clip(layer);
}

static void il_ctrl_button_paint(il_control* ctrl_p)
{
    il_button* button_p = (il_button*)ctrl_p;

    if(!button_p)
        return;

    switch(button_p->type)
    {
        case IL_TEXT_BUTTON:
            il_ctrl_text_button_paint(ctrl_p);
            break;

        case IL_IMAGE_BUTTON:
            il_ctrl_image_button_paint(ctrl_p);
            break;

        default:
            //warn
            break;
    }
}

static il_ret il_ctrl_button_change_status(il_control* ctrl_p, il_button_status status)
{
    il_ret ret = IL_OK;
    il_button* button_p = (il_button*)ctrl_p;

    if(!button_p || status == button_p->status)
    {
        return IL_INVALID_PARAM;
    }

    button_p->status = status;
    ctrl_p->paint_hdlr(ctrl_p);
    il_ctrl_flush();

    if(button_p->status == IL_BUTTON_DOWN)
    {
        ILINT i = 0;

        for(i = 0; i < IL_BUTTON_SUPPORT_CALLBACK_MAX; i++)
        {
            if(button_p->down_cb[i])
            {
                button_p->down_cb[i]();
            }
        }
    }
    else if(button_p->status == IL_BUTTON_UP)
    {
        ILINT i = 0;

        for(i = 0; i < IL_BUTTON_SUPPORT_CALLBACK_MAX; i++)
        {
            if(button_p->up_cb[i])
            {
                button_p->up_cb[i]();
            }
        }
    }

    return ret;
}

static il_ret il_ctrl_button_set_show_offset(il_control* ctrl_p, ILINT x_off, ILINT y_off)
{
    il_button* button_p = (il_button*)ctrl_p;
    ILINT i;

    if(!button_p)
        return IL_INVALID_PARAM;

    if(button_p->type == IL_IMAGE_BUTTON)
    {
        for(i = 0; i < IL_BUTTON_STATUS_MAX; i++)
        {
            if(button_p->elem.images[i])
            {
                button_p->elem.images[i]->set_show_type((il_control*)button_p->elem.images[i], IL_IMAGE_CUSTOM);
                button_p->elem.images[i]->set_show_offset((il_control*)button_p->elem.images[i], x_off, y_off);
            }
        }
    }

    return IL_OK;
}

static il_ret il_ctrl_button_reset_status(il_control* ctrl_p)
{
    il_ret ret = IL_OK;
    il_button* button_p = (il_button*)ctrl_p;

    if(!ctrl_p)
    {
        return IL_INVALID_PARAM;
    }

    button_p->status = IL_BUTTON_UP;
    ctrl_p->paint_hdlr(ctrl_p);
    il_ctrl_flush();
    return ret;
}

#define IL_CTRL_BUTTON_ADD_ITEM_TO_LIST(ctrl_p,list,list_counts,item) \
    {\
        il_ret ret = IL_OK;\
        il_button* button_p = (il_button*)ctrl_p;\
        ILINT i = 0;\
        if(!button_p)\
        {\
            return IL_INVALID_PARAM;\
        }\
        for (i = 0; i < list_counts; i++)\
        {\
            if(list[i] == item)\
            {\
                return ret;\
            }\
        }\
        for(i = 0; i< list_counts; i++)\
        {\
            if(list[i] == 0)\
            {\
                list[i] = item;\
                break;\
            }\
        }\
        \
        return ret;\
    }


#define IL_CTRL_BUTTON_DELETE_ITEM_FROM_LIST(ctrl_p,list,list_counts,item) \
    {\
        il_ret ret = IL_OK;\
        il_button* button_p = (il_button*)ctrl_p;\
        ILINT i = 0;\
        \
        if(!button_p)\
        {\
            return IL_INVALID_PARAM;\
        }\
        \
        for (i = 0; i < list_counts; i++)\
        {\
            if(list[i] == item)\
            {\
                list[i] = 0;\
            }\
        }\
        return ret;\
    }


static il_ret il_ctrl_button_add_keycode(il_control* ctrl_p, ILINT key_code)
{
    IL_CTRL_BUTTON_ADD_ITEM_TO_LIST(ctrl_p, button_p->key_code_list, IL_BUTTON_SUPPORT_KEYCODE_MAX, key_code);
}

static il_ret il_ctrl_button_delete_keycode(il_control* ctrl_p, ILINT key_code)
{
    IL_CTRL_BUTTON_DELETE_ITEM_FROM_LIST(ctrl_p, button_p->key_code_list, IL_BUTTON_SUPPORT_KEYCODE_MAX, key_code);
}

static il_ret il_ctrl_button_add_down_cb_by_status(il_control* ctrl_p, il_button_cb p)
{
    IL_CTRL_BUTTON_ADD_ITEM_TO_LIST(ctrl_p, button_p->down_cb, IL_BUTTON_SUPPORT_CALLBACK_MAX, p);
}

static il_ret il_ctrl_button_delete_down_cb_by_status(il_control* ctrl_p, il_button_cb p)
{
    IL_CTRL_BUTTON_DELETE_ITEM_FROM_LIST(ctrl_p, button_p->down_cb, IL_BUTTON_SUPPORT_CALLBACK_MAX, p);
}

static il_ret il_ctrl_button_add_up_cb_by_status(il_control* ctrl_p, il_button_cb p)
{
    IL_CTRL_BUTTON_ADD_ITEM_TO_LIST(ctrl_p, button_p->up_cb, IL_BUTTON_SUPPORT_CALLBACK_MAX, p);
}

static il_ret il_ctrl_button_delete_up_cb_by_status(il_control* ctrl_p, il_button_cb p)
{
    IL_CTRL_BUTTON_DELETE_ITEM_FROM_LIST(ctrl_p, button_p->up_cb, IL_BUTTON_SUPPORT_CALLBACK_MAX, p);
}

static il_ret il_ctrl_button_add_cb_by_status(il_control* ctrl_p, il_button_status status, il_button_cb p)
{
    if(status == IL_BUTTON_UP)
    {
        return il_ctrl_button_add_up_cb_by_status(ctrl_p, p);
    }
    else if(status == IL_BUTTON_DOWN)
    {
        return il_ctrl_button_add_up_cb_by_status(ctrl_p, p);
    }
    else
    {
        return IL_INVALID_PARAM;
    }
}

static il_ret il_ctrl_button_delete_cb_by_status(il_control* ctrl_p, il_button_status status, il_button_cb p)
{
    if(status == IL_BUTTON_UP)
    {
        return il_ctrl_button_delete_up_cb_by_status(ctrl_p, p);
    }
    else if(status == IL_BUTTON_DOWN)
    {
        return il_ctrl_button_delete_up_cb_by_status(ctrl_p, p);
    }
    else
    {
        return IL_INVALID_PARAM;
    }
}


static il_ret il_ctrl_button_pen_hdlr(il_control* ctrl_p, ILINT event, ILINT x, ILINT y)
{
    il_ret ret = IL_OK;
    il_button* button_p = (il_button*)ctrl_p;

    if(!button_p)
    {
        return IL_INVALID_PARAM;
    }

    if(button_p->status == IL_BUTTON_DISABLE)
    {
        return IL_IGNORE;
    }

    if(event != VM_PEN_EVENT_TAP && !button_p->if_selected_by_down_event)
    {
        return IL_IGNORE;
    }

    if(event == VM_PEN_EVENT_TAP && IL_POINT_IN_RECT(x, y, ctrl_p->area))
    {
        button_p->if_selected_by_down_event = TRUE;
        button_p->change_status(ctrl_p, IL_BUTTON_DOWN);
    }

    if(button_p->if_selected_by_down_event && event == VM_PEN_EVENT_RELEASE && IL_POINT_IN_RECT(x, y, ctrl_p->area))
    {
        button_p->if_selected_by_down_event = FALSE;
        button_p->change_status(ctrl_p, IL_BUTTON_UP);
    }
    else if(event == VM_PEN_EVENT_MOVE && !IL_POINT_IN_RECT(x, y, ctrl_p->area))
    {
        button_p->if_selected_by_down_event = FALSE;
        button_p->reset_status(ctrl_p);
    }
    //else if(event != VM_PEN_EVENT_TAP && button_p->if_selected_by_down_event)
    //{
    //    button_p->if_selected_by_down_event = FALSE;
    //    button_p->reset_status(ctrl_p);
    //}
    else
    {
        return IL_IGNORE;
    }

    return ret;
}

static il_ret il_ctrl_button_key_hdlr(il_control* ctrl_p, ILINT event, ILINT keycode)
{
    il_button* button_p = (il_button*)ctrl_p;
    ILINT i = 0;

    if(!button_p)
    {
        return IL_INVALID_PARAM;
    }

    for(i = 0; i < IL_BUTTON_SUPPORT_KEYCODE_MAX; i++)
    {
        if(button_p->key_code_list[i] == keycode)
        {
            if(event == VM_KEY_EVENT_DOWN)
            {
                button_p->change_status(ctrl_p, IL_BUTTON_DOWN);
            }
            else if(event == VM_KEY_EVENT_UP)
            {
                button_p->change_status(ctrl_p, IL_BUTTON_UP);
            }

            return IL_OK;
        }
    }

    return IL_IGNORE;
}

static void il_ctrl_button_move(il_control* ctrl_p, ILINT x_off, ILINT y_off)
{
    il_button* button_p = (il_button*)ctrl_p;

    if(!button_p)
        return;

    button_p->base.area.x += (ILINT16)x_off;
    button_p->base.area.y += (ILINT16)y_off;

    if(button_p->type == IL_TEXT_BUTTON)
    {
        if(button_p->elem.label)
            button_p->elem.label->base.move((il_control*)button_p->elem.label, x_off, y_off);
    }
    else if(button_p->type == IL_IMAGE_BUTTON)
    {
        ILINT i = 0;

        for (i = 0; i < ARRAY_SIZE(button_p->elem.images); i++)
        {
            if(button_p->elem.images[i])
                button_p->elem.images[i]->base.move((il_control*)button_p->elem.images[i], x_off, y_off);
        }
    }
}

il_button* il_ctrl_button_create(ILUINT8* paint_buf, il_rect area, il_button_type type,
                                 ILWSTR param1, ILWSTR param2, ILWSTR param3, ILUINT img_src_type)
{
    il_button* button_p = NULL;

    if(!paint_buf || type < IL_TEXT_BUTTON || type >= IL_BUTTON_TYPE_MAX || !param1 || vm_wstrlen(param1) <= 0)
    {
        return button_p;
    }

    if(type == IL_IMAGE_BUTTON && (!param2 || vm_wstrlen(param2) <= 0))
    {
        return button_p;
    }

    button_p = vm_calloc(sizeof(il_button));

    if(button_p == NULL)
    {
        return button_p;
    }

    il_ctrl_init((il_control*)button_p, paint_buf, &area);
    button_p->base.paint_hdlr = il_ctrl_button_paint;
    button_p->base.ctrl_type = IL_CTRL_BUTTON;
    button_p->base.move = il_ctrl_button_move;
    button_p->base.pen_hdlr = il_ctrl_button_pen_hdlr;
    button_p->base.key_hdlr = il_ctrl_button_key_hdlr;
    button_p->if_selected_by_down_event = FALSE;
    button_p->type = type;
    button_p->status = IL_BUTTON_UP;
    button_p->change_status = il_ctrl_button_change_status;
    button_p->reset_status = il_ctrl_button_reset_status;
    button_p->add_keycode = il_ctrl_button_add_keycode;
    button_p->delete_keycode = il_ctrl_button_delete_keycode;
    button_p->add_cb_by_status = il_ctrl_button_add_cb_by_status;
    button_p->delete_cb_by_status = il_ctrl_button_delete_cb_by_status;
    button_p->set_show_offset = il_ctrl_button_set_show_offset;

    if(button_p->type == IL_TEXT_BUTTON)
    {
        ILUINT param[1];
        param[0] = (ILUINT)param1;
        button_p->elem.label = (il_label*)il_ctrl_create(IL_CTRL_LABEL, paint_buf, area, 1, (void**)param);

        if(!button_p->elem.label)
        {
            vm_free(button_p);
            button_p = NULL;
            return button_p;
        }
    }
    else if(button_p->type == IL_IMAGE_BUTTON)
    {
        ILUINT param[3];
        //create status UP image
        param[0] = (ILUINT)img_src_type;
        param[1] = (ILUINT)param1;
        param[2] = (ILUINT)FALSE;
        button_p->elem.images[IL_BUTTON_UP] = (il_image*)il_ctrl_create(IL_CTRL_IMAGE, paint_buf, area, 3, (void**)param);

        if(!button_p->elem.images[IL_BUTTON_UP])
        {
            vm_free(button_p);
            button_p = NULL;
            return button_p;
        }

        //create status DOWN image
        param[1] = (ILUINT)param2;
        button_p->elem.images[IL_BUTTON_DOWN] = (il_image*)il_ctrl_create(IL_CTRL_IMAGE, paint_buf, area, 3, (void**)param);

        if(!button_p->elem.images[IL_BUTTON_DOWN])
        {
            il_ctrl_destroy((il_control*)button_p->elem.images[IL_BUTTON_DOWN]);
            vm_free(button_p);
            button_p = NULL;
            return button_p;
        }

        //create status DISABLE image
        if(param3 && vm_wstrlen(param3) > 0)
        {
            param[1] = (ILUINT)param3;
            button_p->elem.images[IL_BUTTON_DISABLE] = (il_image*)il_ctrl_create(IL_CTRL_IMAGE, paint_buf, area, 3, (void**)param);

            if(!button_p->elem.images[IL_BUTTON_DISABLE])
            {
                il_ctrl_destroy((il_control*)button_p->elem.images[IL_BUTTON_DOWN]);
                il_ctrl_destroy((il_control*)button_p->elem.images[IL_BUTTON_DISABLE]);
                vm_free(button_p);
                button_p = NULL;
                return button_p;
            }
        }
    }

    return button_p;
}

il_ret il_ctrl_button_destroy(il_button* ctrl_button_p)
{
    il_ret ret = IL_OK;

    if(!ctrl_button_p)
    {
        return IL_INVALID_PARAM;
    }

    return ret;
}